package com.playmodule.view;

import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.widget.FrameLayout;

import com.haijing.highglass.HmdCtrl;
import com.hg.highglass_library.R;
import com.playmodule.MediaUtil;
import com.playmodule.vr.projections.ProjectionFactory;
import com.playmodule.vr.utils.ShakeEventListener;

import org.hitlabnz.sensor_fusion_demo.orientationProvider.AccelerometerCompassProvider;
import org.hitlabnz.sensor_fusion_demo.orientationProvider.CalibratedGyroscopeProvider;
import org.hitlabnz.sensor_fusion_demo.orientationProvider.GravityCompassProvider;
import org.hitlabnz.sensor_fusion_demo.orientationProvider.ImprovedOrientationSensor1Provider;
import org.hitlabnz.sensor_fusion_demo.orientationProvider.ImprovedOrientationSensor2Provider;
import org.hitlabnz.sensor_fusion_demo.orientationProvider.OrientationProvider;
import org.hitlabnz.sensor_fusion_demo.orientationProvider.RotationVectorProvider;

/**
 * Created by wangjianqiang on 2016/11/17.
 */
public class PlayView extends FrameLayout implements SensorEventListener {
    private final int VIDEO_MODE_2D = 0;
    private final int VIDEO_MODE_LR = 1;
    private final int VIDEO_MODE_UD = 2;
    private boolean isInVrMode = false;
    private VideoDisplayView mVideoDisplayView;
    private VideoDisplayLeftRightView mUpAndDownView;
    private int mVideoMode = -1;// 0 2d 1 lr 2 ud;
    private MediaUtil mediaHelper;
    private int screenSizeMode = 0;

    private float mAspectRatio;
    private boolean mAutoRatio;
    private int mFormatMode;//视频mode 0 2d 1/lr 2/ud

    private OrientationProvider mOrientationProvider;
    private boolean mPassThrough;
    private int mProjectionMode = 1;
    private int mScreenMode = 1;//0 3d 1 2d
    private ShakeEventListener mSensorListener;
    private SensorManager mSensorManager;
    private int mShakeAction;
    private VrSurfaceView mVrView;
    private boolean hasRegistered = false;

    private int rl_mode = 0;// 0 close 1 open
    private PlayViewInterface playViewInterface;
    private boolean inSmallSize = true;
    private int curScreenMode = 1;
    boolean is4k = false;

    public PlayView(Context context) {
        super(context);
        init();
    }

    public PlayView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PlayView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        LayoutInflater.from(getContext()).inflate(R.layout.play_view_layout, this);
        mVideoDisplayView = (VideoDisplayView) findViewById(R.id.surface_view);
        mVrView = (VrSurfaceView) findViewById(R.id.vr_surface_view);
        mUpAndDownView = (VideoDisplayLeftRightView) findViewById(R.id.up_down_view);

        initSensor();
        loadConfig();
    }

    public void setSmallWh() {
        mVideoDisplayView.setSmallWh();
    }

    public void onPause() {
        if (mVrView.getVisibility() == VISIBLE && hasRegistered) {
            hasRegistered = false;
            this.mVrView.onPause();
        }
        try {
            this.mOrientationProvider.stop();
        } catch (Exception e) {

        }
        try {
            this.mSensorManager.unregisterListener(this.mSensorListener);
        } catch (Exception e) {

        }
        try {
            this.mSensorManager.unregisterListener(this);
        } catch (Exception e) {

        }
    }

    public void onResume() {
        if (mVrView.getVisibility() == VISIBLE && !hasRegistered) {
            hasRegistered = true;
            this.mVrView.onResume();
            this.mOrientationProvider.start();
            this.mSensorManager.registerListener(this.mSensorListener, this.mSensorManager.getDefaultSensor(1), 2);
            this.mSensorManager.registerListener(this, this.mSensorManager.getDefaultSensor(8), 3);
            HmdCtrl.openVR(1);
        }
    }

    public void setActivity(PlayViewInterface playViewInterface, MediaUtil mediaHelper) {
        this.playViewInterface = playViewInterface;
        this.mediaHelper = mediaHelper;
        mUpAndDownView.setMediaHelper(mediaHelper);
        mVrView.setMediaHelper(mediaHelper);
        mVideoDisplayView.setMediaHelper(mediaHelper);
    }

    public void setMode(boolean isVR, int videoMode) {
        if (isVR) {
            HmdCtrl.openVR(1);
        } else {
            HmdCtrl.openVR(0);
        }
        switch (videoMode) {
            case 0:
                mScreenMode = 1;
                break;
            case 1:
            case 2:
                mScreenMode = 0;
                break;
        }
        mFormatMode = videoMode;
        if (this.isInVrMode ^ isVR) {
            if (isVR) {
                mVideoMode = videoMode;
                openVR();
            } else {
                mVrView.setVisibility(GONE);
                onPause();
                if (videoMode == VIDEO_MODE_UD) {
                    openUD();
                    if (rl_mode == 0) {
                        mUpAndDownView.setMode(0);
                    } else {
                        mUpAndDownView.setMode(2);
                    }
                } else {
                    if (videoMode == VIDEO_MODE_2D) {
                        openCommon();
                    }
                    if (videoMode == VIDEO_MODE_LR) {
                        if (rl_mode == 0) {
                            openCommon();
                        } else {
                            openUD();
                            mUpAndDownView.setMode(1);
                        }
                    }

                }
                mVideoMode = videoMode;
            }
            isInVrMode = isVR;
        } else {
            if (isInVrMode) {
                this.mVrView.setProjection(this.mProjectionMode, this.mFormatMode, this.mAspectRatio, false);
                mVrView.getRenderer().setScreenMode(this.mScreenMode);
            } else {
                if (mVideoMode != videoMode) {
                    if (videoMode == VIDEO_MODE_UD) {
                        mVideoDisplayView.setVisibility(GONE);
                        openUD();
                        if (rl_mode == 0) {
                            mUpAndDownView.setMode(0);
                        } else {
                            mUpAndDownView.setMode(2);
                        }
                    } else {
                        //videoMode = 0 || 1   && !=mVideoMode
                        if (mVideoMode == VIDEO_MODE_UD && rl_mode == 0) {
                            mUpAndDownView.setVisibility(GONE);
                        }
                        if (videoMode == VIDEO_MODE_2D) {
                            mUpAndDownView.setVisibility(GONE);
                            openCommon();
                        } else {
                            if (rl_mode == 0) {
                                mUpAndDownView.setVisibility(GONE);
                                openCommon();
                            } else {
                                mVideoDisplayView.setVisibility(GONE);
                                openUD();
                                mUpAndDownView.setMode(1);
                            }
                        }
                    }
                    mVideoMode = videoMode;
                }
            }
        }
    }

    public void open4K(boolean is4K) {
        this.is4k = is4K;
        if (is4K) {
            mVideoDisplayView.setVisibility(GONE);
            mUpAndDownView.setVisibility(GONE);
            mUpAndDownView.setMode(VideoDisplayLeftRightView.MODE_4K);
            openUD();
        }
    }

    //used for online video
    public void setMode1(boolean isVR, int videoMode) {
        if (rl_mode == 1) {
            openrl(0);
        }
        switch (videoMode) {
            case 0:
                mScreenMode = 1;
                break;
            case 1:
            case 2:
                mScreenMode = 0;
                break;
        }
        mFormatMode = videoMode;
        if (this.isInVrMode ^ isVR) {
            if (isVR) {
                mVideoMode = videoMode;
                openVR();
            } else {
                mVrView.setVisibility(GONE);
                onPause();
                if (videoMode == VIDEO_MODE_UD) {
                    openUD();
                    if (rl_mode == 0) {
                        mUpAndDownView.setMode(VideoDisplayLeftRightView.UP_DOWN);
                    } else {
                        mUpAndDownView.setMode(VideoDisplayLeftRightView.RIGHT_LEFT_UP_DOWN);
                    }
                } else {
                    if (videoMode == VIDEO_MODE_2D) {
                        openCommon();
                    }
                    if (videoMode == VIDEO_MODE_LR) {
                        if (rl_mode == 0) {
                            openCommon();
                        } else {
                            openUD();
                            mUpAndDownView.setMode(1);
                        }
                    }

                }
                mVideoMode = videoMode;
            }
            isInVrMode = isVR;
        } else {
            if (isInVrMode) {
                this.mVrView.setProjection(this.mProjectionMode, this.mFormatMode, this.mAspectRatio, false);
                mVrView.getRenderer().setScreenMode(this.mScreenMode);
            } else {
                rl_mode = 0;
                if (mVideoMode != videoMode) {
                    if (videoMode == VIDEO_MODE_UD) {
                        mVideoDisplayView.setVisibility(GONE);
                        openUD();
                        if (rl_mode == 0) {
                            mUpAndDownView.setMode(0);
                        } else {
                            mUpAndDownView.setMode(2);
                        }
                    } else {
                        mUpAndDownView.setVisibility(GONE);
                        openCommon();
                    }
                    mVideoMode = videoMode;
                }
            }
        }
    }

    public void setRl_modeDisable() {
        rl_mode = 0;
    }

    public void openrl(int mode) {
        if (rl_mode != mode) {
            this.rl_mode = mode;
            if (!isInVrMode) {
                if (rl_mode == 0) {
                    if (mVideoMode == VIDEO_MODE_LR) {
                        mUpAndDownView.setMode(VideoDisplayLeftRightView.UP_DOWN);
                        mUpAndDownView.setVisibility(GONE);
                        openCommon();
                    } else if (mVideoMode == VIDEO_MODE_UD) {
                        mUpAndDownView.setMode(VideoDisplayLeftRightView.UP_DOWN);
                    }
                } else {
                    if (mVideoMode == VideoDisplayLeftRightView.RIGHT_LEFT) {
                        mVideoDisplayView.setVisibility(GONE);
                        openUD();
                        mUpAndDownView.setMode(VideoDisplayLeftRightView.RIGHT_LEFT);
                    } else if (mVideoMode == VideoDisplayLeftRightView.RIGHT_LEFT_UP_DOWN) {
                        mUpAndDownView.setMode(VideoDisplayLeftRightView.RIGHT_LEFT_UP_DOWN);
                    }
                }
            }
        }
    }

    //used for online video
    public void openrl1(int mode) {
        if (rl_mode != mode) {
            this.rl_mode = mode;
            if (rl_mode == 0) {
                if (mVideoMode == VIDEO_MODE_LR) {
                    mUpAndDownView.setMode(VideoDisplayLeftRightView.UP_DOWN);
                    mUpAndDownView.setVisibility(GONE);
                    openCommon();
                } else if (mVideoMode == VIDEO_MODE_UD) {
                    mUpAndDownView.setMode(VideoDisplayLeftRightView.UP_DOWN);
                }
            } else {
                mVideoMode = VideoDisplayLeftRightView.RIGHT_LEFT;
                mVideoDisplayView.setVisibility(GONE);
                openUD();
                mUpAndDownView.setMode(VideoDisplayLeftRightView.RIGHT_LEFT);
            }
        }
    }

    //vr
    private void loadConfig() {
        try {
            SharedPreferences localSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
            this.mProjectionMode = getIntFromSharedPrefs(localSharedPreferences, "projectionPref", 1);
            this.mFormatMode = getIntFromSharedPrefs(localSharedPreferences, "formatPref", 0);
            boolean trackOrientation = localSharedPreferences.getBoolean("orientationPref", true);
            this.mVrView.getRenderer().setTrackOrientation(trackOrientation);
            boolean ambilight = localSharedPreferences.getBoolean("ambilightPref", false);
            ProjectionFactory.getInstance().setAmbilight(ambilight);
            int i3 = getIntFromSharedPrefs(localSharedPreferences, "fovPref", 60);
            if ((i3 > 0) && (i3 < 180)) {
                this.mVrView.getRenderer().setFov(60);
            }
            this.mScreenMode = getIntFromSharedPrefs(localSharedPreferences, "screenModePref", 1);
            this.mVrView.getRenderer().setScreenMode(this.mScreenMode);
            int viewportHorizontalPadding = getIntFromSharedPrefs(localSharedPreferences, "viewportHorizontalPadding", 0);
            int viewportVerticalPadding = getIntFromSharedPrefs(localSharedPreferences, "viewportVerticalPadding", 0);
            int viewportCenterPadding = getIntFromSharedPrefs(localSharedPreferences, "viewportCenterPadding", 0);
            this.mVrView.getRenderer().setViewportsPadding(viewportHorizontalPadding, viewportVerticalPadding, viewportCenterPadding);
            this.mShakeAction = getIntFromSharedPrefs(localSharedPreferences, "shakePref", 3);
            this.mAutoRatio = localSharedPreferences.getBoolean("planeAutoRatio", true);
            if (!this.mAutoRatio) {
                this.mAspectRatio = getFloatFromSharedPrefs(localSharedPreferences, "planeRatio", 1.33F);
            }
            ProjectionFactory.getInstance().setSphereSettings(getFloatFromSharedPrefs(localSharedPreferences, "sphereWidth", 1.0F), getFloatFromSharedPrefs(localSharedPreferences, "sphereHeight", 1.0F), getFloatFromSharedPrefs(localSharedPreferences, "sphereDepth", 1.0F), getIntFromSharedPrefs(localSharedPreferences, "sphereSlices", 32), getIntFromSharedPrefs(localSharedPreferences, "sphereStacks", 32));
            ProjectionFactory.getInstance().setDomeSettings(getFloatFromSharedPrefs(localSharedPreferences, "domeHorizontalCoverage", 0.5F), getFloatFromSharedPrefs(localSharedPreferences, "domeVerticalCoverage", 0.6F), getIntFromSharedPrefs(localSharedPreferences, "domeSlices", 32), getIntFromSharedPrefs(localSharedPreferences, "domeStacks", 32));
            ProjectionFactory.getInstance().setFullDomeSettings(getFloatFromSharedPrefs(localSharedPreferences, "fullDomeCoverage", 180.0F), getFloatFromSharedPrefs(localSharedPreferences, "fullDomeTilt", 90.0F), getFloatFromSharedPrefs(localSharedPreferences, "fullDomeHeading", 0.0F), getIntFromSharedPrefs(localSharedPreferences, "fullDomeSlices", 32), getIntFromSharedPrefs(localSharedPreferences, "fullDomeStacks", 32));
            ProjectionFactory.getInstance().setCylinderSettings(getFloatFromSharedPrefs(localSharedPreferences, "cylinderScale", 1.0F), getFloatFromSharedPrefs(localSharedPreferences, "cylinderAngle", 360.0F), getIntFromSharedPrefs(localSharedPreferences, "cylinderSlices", 32), getIntFromSharedPrefs(localSharedPreferences, "cylinderStacks", 16));
            updateProjection();
            switchOrientationProvider(getIntFromSharedPrefs(localSharedPreferences, "orientationProviderPref", 0));
            if (this.mOrientationProvider != null) {
                this.mOrientationProvider.setFlipX(localSharedPreferences.getBoolean("mirrorModePref", false));
            }
        } catch (Exception e) {
        }

    }

    private void executeAction(int paramInt) {
        switch (paramInt) {
            case 1:
                calibrate();
                break;
        }
    }

    private float getFloatFromSharedPrefs(SharedPreferences paramSharedPreferences, String paramString, float paramFloat) {
        if (!paramSharedPreferences.contains(paramString)) {
            return paramFloat;
        }
        String str = paramSharedPreferences.getString(paramString, Float.toString(paramFloat));
        float value = str == null ? 0 : Float.valueOf(str);
        return value;
    }

    private int getIntFromSharedPrefs(SharedPreferences paramSharedPreferences, String paramString, int paramInt) {
        if (!paramSharedPreferences.contains(paramString)) {
            return paramInt;
        }
        String str = paramSharedPreferences.getString(paramString, Integer.toString(paramInt));
        int value = str == null ? 0 : Integer.valueOf(str);
        return value;
    }

    private void updateProjection() {
        this.mVrView.setProjection(this.mProjectionMode, this.mFormatMode, this.mAspectRatio, false);
    }


    public void calibrate() {
        this.mVrView.getRenderer().calibrate();
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    public void onSensorChanged(SensorEvent event) {
        if (mScreenMode == 3) {
            if (event.sensor.getType() == 8) {
                if (event.values[0] == 0) {
                    mVrView.getRenderer().setScreenMode(0);
                } else {
                    mVrView.getRenderer().setScreenMode(1);
                }
            }
        }
    }

    private void switchOrientationProvider(int paramInt) {
        try {
            if (this.mSensorManager == null) {
                this.mSensorManager = ((SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE));
            }
            if (this.mOrientationProvider != null) {
                this.mOrientationProvider.stop();
            }
            switch (paramInt) {
                case 1:
                    this.mOrientationProvider = new ImprovedOrientationSensor1Provider(this.mSensorManager);
                    break;
                case 2:
                    this.mOrientationProvider = new RotationVectorProvider(this.mSensorManager);
                    break;
                case 3:
                    this.mOrientationProvider = new CalibratedGyroscopeProvider(this.mSensorManager);
                    break;
                case 4:
                    this.mOrientationProvider = new GravityCompassProvider(this.mSensorManager);
                    break;
                case 5:
                    this.mOrientationProvider = new AccelerometerCompassProvider(this.mSensorManager);
                    break;
                default:
                    this.mOrientationProvider = new ImprovedOrientationSensor2Provider(this.mSensorManager);
                    break;
            }
            this.mOrientationProvider.start();
            this.mVrView.setOrientationProvider(this.mOrientationProvider);
            hasRegistered = true;
        } catch (Exception localException) {
        }
    }

    private void updateAspectRatio(int paramInt1, int paramInt2) {
        if (!this.mAutoRatio) {
            return;
        }
        if ((paramInt1 != 0) && (paramInt2 != 0)) {
            this.mAspectRatio = (paramInt1 / paramInt2);
            return;
        }
        this.mAspectRatio = 1.33F;
    }

    private void initSensor() {
        this.mSensorListener = new ShakeEventListener();
        this.mSensorListener.setOnShakeListener(new ShakeEventListener.OnShakeListener() {
            public void onShake() {
                executeAction(mShakeAction);
            }
        });
    }


    public void setScreenSizeMode(int i) {
        screenSizeMode = i;
        if (mVideoDisplayView.getVisibility() == VISIBLE)
            mVideoDisplayView.setScreenSizeMode(i);
    }

    private void openVR() {
        MediaPlayer mediaPlayer = mediaHelper.getmMediaPlayer();
        mediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
            @Override
            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                updateAspectRatio(width, height);
                updateProjection();
            }
        });
        this.mVrView.setProjection(this.mProjectionMode, this.mFormatMode, this.mAspectRatio, false);
        mVrView.getRenderer().setScreenMode(this.mScreenMode);
        mVrView.setVisibility(VISIBLE);

        mVrView.setMediaPlayer();
        mVrView.onResume();
        mVideoDisplayView.setVisibility(GONE);
        mUpAndDownView.setVisibility(GONE);
    }

    private void openUD() {
        mUpAndDownView.setMediaPlayer();
        mUpAndDownView.setVisibility(VISIBLE);
    }

    private void openCommon() {
        if (is4k) {
            open4K(true);
        } else {
            mVideoDisplayView.setMediaPlayer();
            mVideoDisplayView.setVisibility(VISIBLE);
        }
    }

    public boolean canPlay() {
        if (isInVrMode) {
            return mVrView.getRenderer().hasCreated;
        } else {
            if (is4k) {
                return mUpAndDownView.hasCreated;
            }
            if (mVideoMode == VIDEO_MODE_2D) {
                return mVideoDisplayView.hasCreated();
            } else if (mVideoMode == VIDEO_MODE_LR) {
                if (rl_mode == 1) {
                    return mUpAndDownView.hasCreated;
                } else {
                    return mVideoDisplayView.hasCreated();
                }
            } else if (mVideoMode == VIDEO_MODE_UD) {
                return mUpAndDownView.hasCreated;
            } else {
                return mVideoDisplayView.hasCreated();
            }
        }
    }

    public void setFullSize() {
        if (inSmallSize) {
            inSmallSize = false;
            if (playViewInterface != null) {
                playViewInterface.setInSmallSize(false);
            }
            mVideoDisplayView.setFullSize();
            setScreenSizeMode(curScreenMode);
        }
    }

    public void setSmallSize(boolean finish) {
        inSmallSize = true;
        if (playViewInterface != null) {
            playViewInterface.setInSmallSize(true);
        }
        if (!finish) {
            mVideoDisplayView.setSmallSize();
            setScreenSizeMode(curScreenMode);
        }
    }

    public SurfaceHolder getSurfaceHolder() {
        if (mVideoDisplayView.getVisibility() == VISIBLE) {
            return mVideoDisplayView.getHolder();
        }
        return null;
    }

    public interface PlayViewInterface {
        void setInSmallSize(boolean inSmallSize);
    }
}
